#ifndef _RING_QUEUE_HPP_
#define _RING_QUEUE_HPP_
#include <iostream>
#include <vector>
#include <pthread.h>
#include "sem.hpp"
const int g_num = 5;
// 多生产多消费的意义在哪里？？
// 不在于并发的往交易场所放任务和拿任务，而在于并发的在放任务前生产任务，在拿任务后处理任务

// 信号量的本质是一个计数器 -- 计数器的意义是什么？可以不用进入临界区就可以知道临界资源的情况，甚至可以减少临界区内部的判断
// 申请锁 -> 访问与判断 -> 释放锁 -- 本质是我们不清楚临界资源的情况
// 信号量要提前预设资源的情况，而且在pv变化的过程中(原子的)，我们可以在外部就知道临界资源的情况

// 多线程
template<class T>
class RingQueue
{
public:
    RingQueue(int num = g_num)
        :ring_queue_(num)
        ,space_sem(num)
        ,data_sem(0)
        ,num_(num)
        ,c_size_(0)
        ,p_size_(0)
    {
        pthread_mutex_init(&clock,nullptr);
        pthread_mutex_init(&plock,nullptr);
    }
    ~RingQueue()
    {
        pthread_mutex_destory(&clock);
        pthread_mutex_destroy(&plock);
    }
    // 生产者：空间资源，生产者们的临界资源是什么？下标
    void push(const T &out)
    {
        space_sem.p();
        pthread_mutex_lock(&plock);
        c_size_ %= num_;
        ring_queue_[c_size_++] = out;
        pthread_mutex_unlock(&plock);
        data_sem.v();
    }
    // 消费者：数据资源，消费者们的临界资源是什么？下标
    void pop(T *out)
    {
        data_sem.p();
        pthread_mutex_lock(&clock);
        p_size_ %= num_;
        *out = ring_queue_[p_size_++];
        pthread_mutex_unlock(&clock);
        space_sem.v();
    }
private:
    std::vector<T> ring_queue_;
    int num_;
    int c_size_;
    int p_size_;
    sem space_sem;  // 空间资源
    sem data_sem;   // 数据资源
    pthread_mutex_t clock;
    pthread_mutex_t plock;
};






#endif